{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "9c9a416c-c0d3-4bf2-a9df-0817c1709209",
   "metadata": {},
   "source": [
    "- https://ai.google.dev/gemini-api/docs/thinking?hl=zh-cn\n",
    "- 关于 thinking 部分的说明\n",
    "    - https://blog.google/technology/google-deepmind/google-gemini-updates-io-2025/#developer-experience\n",
    "    - Thought summaries\n",
    "        - 2.5 Pro and Flash will now include thought summaries in the Gemini API and in Vertex AI. Thought summaries take the **model’s raw thoughts and organize them into a clear format with headers, key details and information about model actions**, like when they use tools.\n",
    "        - We hope that with a more structured, streamlined format on the model’s thinking process, developers and users will find the interactions with Gemini models easier to understand and debug.\n",
    "- role\n",
    "    - system, user, model, user, model, ..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2ebce397-5556-4686-8fd6-f5b54c8c00d0",
   "metadata": {},
   "source": [
    "### api test"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1e63e1d1-c697-4b35-9d77-3fe1ee8fa6cc",
   "metadata": {},
   "source": [
    "```\n",
    "curl \"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-pro:generateContent\" \\\n",
    "  -H 'Content-Type: application/json' \\\n",
    "  -H 'X-goog-api-key: GEMINI_API_KEY' \\\n",
    "  -X POST \\\n",
    "  -d '{\n",
    "    \"contents\": [\n",
    "      {\n",
    "        \"parts\": [\n",
    "          {\n",
    "            \"text\": \"Explain how AI works in a few words\"\n",
    "          }\n",
    "        ]\n",
    "      }\n",
    "    ]\n",
    "  }\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "57ef345e-2094-4e85-859c-12fb1f64f699",
   "metadata": {},
   "source": [
    "```python\n",
    "payload = {\n",
    "    \"systemInstruction\": {\n",
    "        \"role\": \"system\",\n",
    "        \"parts\": [\n",
    "            {\n",
    "                \"text\": \"Answer in Chinese\" \n",
    "            }\n",
    "        ]\n",
    "    },\n",
    "    \"contents\": [\n",
    "        {\n",
    "            \"role\": \"user\",\n",
    "            \"parts\": [{\"text\": \"who are you?\"}]\n",
    "        }\n",
    "    ],\n",
    "    \"generationConfig\": {\n",
    "        \"temperature\": 0.1,\n",
    "        \"topP\": 1.0,\n",
    "        \"thinkingConfig\": { \"thinkingBudget\": 32768} \n",
    "    },\n",
    "}\n",
    "headers = {\n",
    "    \"Content-Type\": \"application/json\",\n",
    "    \"X-goog-api-key\": api_key # API key now in header!\n",
    "}\n",
    "try:\n",
    "    response = requests.post(API_URL, headers=headers, data=json.dumps(payload))\n",
    "    response.raise_for_status()  # Raises an HTTPError for bad responses (4xx or 5xx)\n",
    "    print(response.json())\n",
    "except requests.exceptions.RequestException as e:\n",
    "    print(f\"Error during API request: {e}\")\n",
    "    if response.status_code == 400:\n",
    "        print(f\"Possible reason for 400: Model '{MODEL_NAME}' might not be available or URL is incorrect for your setup.\")\n",
    "        print(f\"Raw API Response (if available): {response.text}\")\n",
    "    sys.exit(1)\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d5f4b9f9-e1b0-47cf-a425-b0021d8c0ad8",
   "metadata": {
    "jp-MarkdownHeadingCollapsed": true
   },
   "source": [
    "### chat messages"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3223f859-4ab9-43ac-95ac-5d7db06ad74b",
   "metadata": {},
   "source": [
    "- history\n",
    "    - system prompt"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f6a0f25c-11d1-4edf-927e-cc85023d2ad8",
   "metadata": {
    "jp-MarkdownHeadingCollapsed": true
   },
   "source": [
    "### thinking & streaming & token count "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "26593e8d-04ad-4235-9e42-479d41650352",
   "metadata": {},
   "source": [
    "```python\n",
    "import os\n",
    "from google import genai\n",
    "from google.genai import types\n",
    "from dotenv import load_dotenv, find_dotenv\n",
    "\n",
    "load_dotenv(find_dotenv())\n",
    "\n",
    "# 确保您的 API 密钥已通过环境变量或直接在 Client 中配置\n",
    "# client = genai.Client(api_key=\"YOUR_API_KEY\")\n",
    "\n",
    "client = genai.Client(api_key=os.getenv(\"GEMINI_API_KEY\"))\n",
    "\n",
    "prompt = \"\"\"\n",
    "Alice, Bob, and Carol each live in a different house on the same street: red, green, and blue.\n",
    "The person who lives in the red house owns a cat.\n",
    "Bob does not live in the green house.\n",
    "Carol owns a dog.\n",
    "The green house is to the left of the red house.\n",
    "Alice does not own a cat.\n",
    "Who lives in each house, and what pet do they own?\n",
    "\"\"\"\n",
    "\n",
    "prompt = \"\"\"hello\"\"\"\n",
    "\n",
    "thoughts = \"\"\n",
    "answer = \"\"\n",
    "# 创建一个变量来存储最终的元数据\n",
    "final_usage_metadata = None\n",
    "\n",
    "# 获取流式响应的迭代器\n",
    "response_stream = client.models.generate_content_stream(\n",
    "    model=\"gemini-2.5-pro\",\n",
    "    contents=prompt,\n",
    "    config=types.GenerateContentConfig(\n",
    "      thinking_config=types.ThinkingConfig(\n",
    "        include_thoughts=True\n",
    "      )\n",
    "    )\n",
    ")\n",
    "\n",
    "print(\"--- 流式输出 ---\")\n",
    "for chunk in response_stream:\n",
    "  # 从每个数据块中捕获 usage_metadata。\n",
    "  # 循环结束后，该变量将持有最后一个数据块的元数据，其中包含最终总数。\n",
    "  if chunk.usage_metadata:\n",
    "      final_usage_metadata = chunk.usage_metadata\n",
    "\n",
    "  for part in chunk.candidates[0].content.parts:\n",
    "    if not part.text:\n",
    "      continue\n",
    "    elif part.thought:\n",
    "      if not thoughts:\n",
    "        print(\"\\nThoughts summary:\")\n",
    "      print(part.text, end=\"\", flush=True)\n",
    "      thoughts += part.text\n",
    "    else:\n",
    "      if not answer:\n",
    "        print(\"\\nAnswer:\")\n",
    "      print(part.text, end=\"\", flush=True)\n",
    "      answer += part.text\n",
    "\n",
    "print(\"\\n\\n--- 词元统计 ---\")\n",
    "if final_usage_metadata:\n",
    "    # 'thoughts_token_count' 是模型内部原始思考过程消耗的词元数 [citation:3]\n",
    "    print(f\"思考部分的词元数 (Thinking Tokens): {final_usage_metadata.thoughts_token_count}\")\n",
    "    \n",
    "    # 'candidates_token_count' 是最终生成的回答部分的词元数 [citation:1][citation:3]\n",
    "    print(f\"回答部分的词元数 (Answer Tokens): {final_usage_metadata.candidates_token_count}\")\n",
    "    \n",
    "    # 'prompt_token_count' 是您输入提示的词元数 [citation:1]\n",
    "    print(f\"提示部分的词元数 (Prompt Tokens): {final_usage_metadata.prompt_token_count}\")\n",
    "    \n",
    "    # 'total_token_count' 是以上所有部分的总和 [citation:1]\n",
    "    print(f\"总词元数 (Total Tokens): {final_usage_metadata.total_token_count}\")\n",
    "else:\n",
    "    print(\"未能获取 usage_metadata。\")\n",
    "\n",
    "\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "692d0bee-b4cf-4ee2-897e-d2079375febb",
   "metadata": {},
   "source": [
    "### langgraph with gemini"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "92b55cc6-db09-4c50-98aa-7fd3dc33c580",
   "metadata": {},
   "source": [
    "- https://ai.google.dev/gemini-api/docs/langgraph-example?hl=zh-cn"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "torch",
   "language": "python",
   "name": "verl"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
